package wangwenjun.phase3.util;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import util.ThreadUtil;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.stream.IntStream;

/**
 * @author ChangLiang
 * @date 2020/6/27
 */
@Slf4j
public class AQSTest {

    @Test
    @DisplayName("test")
    public void test() throws InterruptedException {
        OneShotLatch latch = new OneShotLatch();
        IntStream.range(0,10).forEach(i->new Thread(()->{
            log.info("尝试获取latch，获取失败那就等待");
            latch.waitAtLatch();
            log.warn("打开门栓进行执行");
        },"my-thread-"+i).start());
        // ensure 10 threads start
        ThreadUtil.sleepForMilliSeconds(100);
        // main thread 打开门栓
        latch.openLatch();
        Thread.currentThread().join();
    }
}

/**
 * 一次性门栓 是共享锁
 */
class OneShotLatch{

    private final Sync sync = new Sync();

    /**
     * 打开门栓
     */
    public void openLatch() {
        sync.releaseShared(0);
    }

    /**
     * 在门栓处汇聚
     */
    public void waitAtLatch() {
        sync.tryReleaseShared(0);
    }

    private class Sync extends AbstractQueuedSynchronizer{

        @Override
        protected int tryAcquireShared(int arg) {
            return getState() == 1 ? 1 : -1;
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            setState(1);
            return true;
        }
    }
}
